/*
 * Matrix.h
 *
 *  Created on: May 26, 2011
 *      Author: gilang
 */

#ifndef MATRIX_H_
#define MATRIX_H_

template<class T>
class Matrix {
private:
	T **values;
	int row;
	int coloumn;
public:
	Matrix() {
		values = NULL;
		row = 0;
		coloumn = 0;
	}
	Matrix(int b, int k) {
		row = b;
		coloumn = k;
		values = new T*[b + 1];
		for (int i = 0; i <= b; i++) {
			values[i] = new T[k + 1];
		}
	}

	void set(int i, int j, T t) {
		values[i][j] = t;
	}
	T & operator()(int i, int j) {
		return values[i][j];
	}

	Matrix<T> operator+(const Matrix<T> &m) {
		Matrix<T> x = Matrix<T> (m.row, m.coloumn);
		T **v = x.values;
		for (int i = 1; i <= x.row; i++) {
			for (int j = 1; j <= x.coloumn; j++) {
				v[i][j] = values[i][j] + m.values[i][j];
			}
		}
		return x;
	}
	Matrix<T> operator-(const Matrix<T> &m) {
		Matrix<T> x = Matrix<T> (m.row, m.coloumn);
		T **v = x.values;
		for (int i = 1; i <= x.row; i++) {
			for (int j = 1; j <= x.coloumn; j++) {
				v[i][j] = values[i][j] - m.values[i][j];
			}
		}
		return x;
	}

	Matrix<T> operator*(const Matrix<T> &m) {
		Matrix<T> x = Matrix<T> (row, m.coloumn);
		T **v = x.values;
		for (int i = 1; i <= x.row; i++) {
			for (int j = 1; j <= x.coloumn; j++) {
				v[i][j] = 0;
				for (int k = 1; k <= coloumn; k++)
					v[i][j] += this(i, k) * m(k, j);
			}
		}
	}

	Matrix<T> operator*(const T &m) {
		for (int i = 1; i <= row; i++) {
			for (int j = 1; j <= coloumn; j++) {
				values[i][j] = m * values[i][j];
			}
		}
		return *this;
	}

	Matrix<T> operator=(const Matrix<T> &m) {
		row = m.row;
		coloumn = m.coloumn;
		values = m.values;
		return *this;
	}

	Matrix & operator+=(const Matrix<T> &m) {
		for (int i = 1; i < row; i++) {
			for (int j = 1; j < coloumn; j++) {
				values[i][j] += m.values[i][j];
			}
		}
		return *this;
	}

	Matrix & operator-=(const Matrix<T> &m) {
		for (int i = 1; i < row; i++) {
			for (int j = 1; j < coloumn; j++) {
				values[i][j] -= m.values[i][j];
			}
		}
		return *this;
	}

	int getRow() const{return row;}
	int getCol() const{return coloumn;}

	virtual ~Matrix() {
	}
};

#endif /* MATRIX_H_ */
